home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Taifun / Taifun 040 (1987-11-15)(Ossowski, Stefan)(DE)(PD).zip / Taifun 040 (1987-11-15)(Ossowski, Stefan)(DE)(PD).adf / A68k / CodeGen.c < prev    next >
C/C++ Source or Header  |  1989-01-18  |  19KB  |  654 lines

  1. /*------------------------------------------------------------------*/
  2. /*                                    */
  3. /*              MC68000 Cross Assembler                */
  4. /*                                    */
  5. /*          Copyright    (c) 1985 by Brian R. Anderson            */
  6. /*                                    */
  7. /*         Object code generator - September 2, 1987            */
  8. /*                                    */
  9. /*   This program may be copied    for personal, non-commercial use    */
  10. /*   only, provided that the above copyright notice is included        */
  11. /*   on    all copies of the source code.    Copying    for any    other use   */
  12. /*   without the consent of the    author is prohibited.            */
  13. /*                                    */
  14. /*------------------------------------------------------------------*/
  15. /*                                    */
  16. /*        Originally published (in Modula-2) in            */
  17. /*        Dr.    Dobb's Journal, April, May, and June 1986.          */
  18. /*                                    */
  19. /*    AmigaDOS conversion copyright (c) 1987 by Charlie Gibbs.    */
  20. /*                                    */
  21. /*------------------------------------------------------------------*/
  22.  
  23. #include <stdio.h>
  24. #include "a68kdef.h"
  25. #include "a68kglb.h"
  26.  
  27. /* Functions */
  28. extern int  LineParts(), GetField(), Instructions(), ObjDir();
  29. extern int  GetSize(), GetInstModeSize(), GetMultReg();
  30. extern int  ReadSymTab(), GetArgs(), GetAReg(),    OpenIncl();
  31. extern long AddrBndW(),    AddrBndL(), GetValue(),    CalcValue();
  32. extern char *malloc();
  33. extern FILE *fopen();
  34.  
  35.  
  36.  
  37. GetObjectCode (dummy) int dummy;
  38. /* Determines the object code for the operation    as well    as the operands    */
  39. /* Returns each    (up to 3 fields), along    with the length    of each.     */
  40. {
  41.     int     quick;
  42.     int     ExtL;        /* Bit pattern for instruction extension word */
  43.     long templong;
  44.     char tempop[MAXLINE];
  45.     register int i, j;
  46.  
  47.     if (Dir != None)
  48.     return;                /* Directive - already done */
  49.  
  50.     if ((Label[0] != '\0') || (OpCode[0] != '\0'))
  51.     PrntAddr = TRUE;        /* Print address at least */
  52.  
  53.     if (OpCode[0] == '\0')
  54.     return;                /* No op code, exit now    */
  55.  
  56.     if (!Instructions (OpLoc)) {    /* Get instruction parts */
  57.     AddrAdv    = InstSize = 0;
  58.     PrntAddr = FALSE;
  59.     Dir = MacCall;            /* Assume it's a macro call */
  60.     if (InF->UPtr == 0)        /* If we're reading from a file */
  61.         InF->Pos = ftell(InFile);    /*  remember where we are */
  62.     tempop[0] = ' ';
  63.     tempop[1] = '\0';
  64.     strcat (tempop,    OpCode);    /* Prepend a blank to OpCode */
  65.     if (ReadSymTab (tempop)) {    /* Search for user macro */
  66.         AddRef (LineCount);
  67.         InFNum++;
  68.         if (--InF <    LowInF)
  69.         LowInF = InF;
  70.         MacCount++;
  71.         Heap2Space (0);        /* Check for space */
  72.         InF->UPtr =    Heap + Hunk2;    /* MACRO statement */
  73.         InF->UPtr += strlen    (InF->UPtr) + 1;  /* Skip over it */
  74.         InF->NPtr =    NextFNS;    /* New stack pointer */
  75.         InF->Line =    0;        /* Line    number in macro    */
  76.         InF->NArg =    GetArgs    ("");   /* Get arguments */
  77.         InF->MCnt =    MacCount;    /* Macro number    */
  78.         if (OuterMac == 0)
  79.         OuterMac = InFNum;    /* Outer macro */
  80.         return;
  81.     }
  82.     if (!OpenIncl (OpCode, InclList)) {
  83.         Error (OpLoc, NoCode);    /* Couldn't open file */
  84.         if (InF->UPtr == 0)    {
  85.         InFile = fopen (InF->NPtr, "r");
  86.         fseek (InFile, InF->Pos, 0);
  87.         }
  88.         return;            /* Return to outer file    */
  89.     }
  90.     InFNum++;            /* Bump    nesting    level */
  91.     if (--InF < LowInF)
  92.         LowInF = InF;
  93.     MacCount++;
  94.     Heap2Space (0);            /* Check for space */
  95.     InF->UPtr = 0;            /* Not a user macro */
  96.     InF->NPtr = NextFNS;        /* New stack pointer */
  97.     InF->Line = 0;            /* Line    number in macro    */
  98.     InF->NArg = GetArgs (OpCode);    /* Get arguments */
  99.     InF->MCnt = MacCount;        /* Macro number    */
  100.     if (OuterMac ==    0)
  101.         OuterMac = InFNum;        /* Outer macro */
  102.     return;
  103.     }
  104.  
  105.     AddrCnt = AddrBndW (AddrCnt);    /* It'll be word-aligned */
  106.  
  107.     if ((AdrModeA != 0)    || (AdrModeB !=    0)) {
  108.     Src.Loc    = SrcLoc;
  109.     Dest.Loc = DestLoc;
  110.     GetOperand (SrcOp, &Src);
  111.     GetOperand (DestOp, &Dest);
  112.     }
  113.     if (EA05z IN AdrModeB) {        /* MOVEM */
  114.     if ((Src.Mode != MultiM) && (Dest.Mode != MultiM)) {
  115.         OpCode[4] =    '\0';           /* MOVEM of a single register */
  116.         Instructions (OpLoc);    /*  becomes a straight MOVE   */
  117.     }
  118.     }
  119.     if ((Src.Mode == Imm)        /* Immediate instructions */
  120.     && (Src.Hunk == ABSHUNK) &&    (Src.Defn <= LineCount)
  121.     && ((EA611 IN AdrModeB)    && (Dest.Mode == DReg)    /* MOVE    */
  122.         && (Src.Value >= -128) && (Src.Value <= 127))
  123.     || ((EA05y IN AdrModeB)                /* ADD/SUB */
  124.         && (Src.Value > 0) && (Src.Value <=    8))) {
  125.         strcat (OpCode,    "Q");   /* Make it ADDQ/SUBQ/MOVEQ */
  126.         Instructions (OpLoc);
  127.     }
  128.     else if ((Dest.Mode    == ARDir) && (Src.Mode <= 12)
  129.     && (((EA05y    | EA611) IN AdrModeB)    /* ADD,    SUB, or    MOVE */
  130.     || (OpM68C IN AdrModeA))) {    /* CMP */
  131.         strcat (OpCode, "A");       /* ADD op,An becomes ADDA etc. */
  132.         Instructions (OpLoc);
  133.     }
  134.     else if ((Src.Mode == Imm)        /* Immediate instructions */
  135.     && ((OpM68D    | OpM68C | OpM68X) IN AdrModeA)) {
  136.     strcat (OpCode,    "I");           /* ADD/AND/OR/SUB, CMP, EOR */
  137.     Instructions (OpLoc);        /* ADD #op,d becomes ADDI etc. */
  138.     }
  139.     else if ((Src.Mode == ARPost) && (Dest.Mode    == ARPost)
  140.     && (OpM68C IN AdrModeA)) {        /* CMP */
  141.     strcat (OpCode,    "M");           /* Generate CMPM if necessary */
  142.     Instructions (OpLoc);
  143.     }
  144.  
  145.  
  146.     /* ----------------    Check for missing operands. ----------------- */
  147.  
  148.     if ((AdrModeA != 0)    || (AdrModeB !=    0))
  149.     if (Src.Mode ==    Null)
  150.         Error (OpLoc+strlen(OpCode), OperErr);    /* No source */
  151.     else if    (Dest.Mode == Null)
  152.         if (((ImmMode & AdrModeB) == ImmMode)
  153.         || (TwoOpsA    IN AdrModeA)
  154.         || (TwoOpsB    IN AdrModeB))
  155.         Error (SrcLoc+strlen(SrcOp), OperErr);    /* No destination */
  156.  
  157.     /* ----------------    Decrement and Branch (DBcc) ----------------- */
  158.  
  159.     if (DecBr IN AdrModeA) {
  160.     if (Src.Mode !=    DReg)
  161.         Error (SrcLoc, ModeErr);
  162.  
  163.     ObjSrc = Dest.Value - AddrCnt -    2; /* Relative branch distance */
  164.  
  165.     if ((ObjSrc>32767) || (ObjSrc <    -32768)    || (Dest.Hunk!=CurrHunk))
  166.         Error (DestLoc, BraErr);    /* Too far to branch */
  167.  
  168.     Dest.Hunk = ABSHUNK;
  169.     AddrAdv    = 4;
  170.     nO = nS    = 2;
  171.     ObjOp =    Op | Src.Rn;
  172.     return;
  173.     }
  174.  
  175.     /* ------------------------    Branch (Bcc) ------------------------ */
  176.     if (Brnch IN AdrModeA) {
  177.     ObjSrc = Src.Value - AddrCnt - 2; /* Relative branch distance */
  178.  
  179.     if (DefLine2 <=    LineCount)
  180.         if ((ObjSrc    >= -128) && (ObjSrc <= 127))
  181.         Size = Byte;        /* Short branch    if possible */
  182.  
  183.     if (Size != Byte) {
  184.         InstSize = 4;
  185.         nS = 2;
  186.         templong = 32767;
  187.     } else {
  188.         InstSize = 2;
  189.         Op |= (ObjSrc & 0x00FF);
  190.         templong = 127;
  191.     }
  192.  
  193.     if ((ObjSrc > templong)    || (ObjSrc < -templong-1)
  194.     || (Src.Hunk !=    CurrHunk))
  195.         Error (SrcLoc, BraErr);    /* Too far to branch */
  196.  
  197.     if (Dest.Mode != Null)
  198.         Error (DestLoc, OperErr);    /* No Destination operand! */
  199.  
  200.     Src.Hunk = ABSHUNK;
  201.     AddrAdv    = InstSize;
  202.     ObjOp =    Op;
  203.     nO = 2;
  204.     return;
  205.     }
  206.  
  207.     if ((Op == JMP) || (Op == JSR))    /* Allows for 'JMP.S' */
  208.     if ((Size == Byte) && (Src.Mode    == AbsL))
  209.         Src.Mode = AbsW;
  210.  
  211. /*  Uses information from Instructions & GetOperand (among others)  */
  212. /*  to complete    calculation of Object Code.                */
  213. /*  Op,    AdrModeA, AdrModeB, Size, and Src & Dest records are all    */
  214. /*  Global variables imported from the SyntaxAnalyzer MODULE.        */
  215.  
  216.     ExtL = 0;
  217.     quick = FALSE;
  218.  
  219. /* Check for 5 special cases first */
  220.  
  221.     if (Op == STOP)
  222.     if ((Src.Mode != Imm) || (Dest.Mode != Null))
  223.         Error (SrcLoc, OperErr);
  224.  
  225.     if (Op == LINK) {
  226.     Op |= Src.Rn;
  227.     if ((Src.Mode != ARDir)    || (Dest.Mode != Imm))
  228.         Error (SrcLoc, ModeErr);
  229.     }
  230.  
  231.     if (Op == SWAP)
  232.     if (!(EA05f IN AdrModeB)) { /* Ignore if PEA instruction */
  233.         Op |= Src.Rn;
  234.         if ((Src.Mode != DReg) || (Dest.Mode != Null))
  235.         Error (SrcLoc, OperErr);
  236.     }
  237.  
  238.     if (Op == UNLK) {
  239.     Op |= Src.Rn;
  240.     if ((Src.Mode != ARDir)    || (Dest.Mode != Null))
  241.         Error (SrcLoc, OperErr);
  242.     }
  243.  
  244. /* Now do generalized address modes */
  245.  
  246.     if ((Ry02 IN AdrModeA) && (Rx911 IN    AdrModeA)) { /*    Two registers */
  247.     if (Op == CMPM)    {        /* Special routine for CMPM */
  248.         Op |= Src.Rn | (Dest.Rn << 9);
  249.         if (Src.Mode != ARPost)
  250.         Error (SrcLoc, ModeErr);
  251.         if (Dest.Mode != ARPost)
  252.         Error (DestLoc,    ModeErr);
  253.     } else {        /* Other two-register instructions */
  254.         Op |= Src.Rn | (Dest.Rn << 9);
  255.         if (RegMem3    IN AdrModeA) {
  256.         if (Src.Mode ==    DReg) {
  257.             if (Dest.Mode != DReg)
  258.             Error (DestLoc,    ModeErr);
  259.         } else if (Src.Mode == ARPre) {
  260.             Op |= 0x0008;
  261.             if (Dest.Mode != ARPre)
  262.             Error (DestLoc,    ModeErr);
  263.         } else
  264.             Error (SrcLoc, OperErr);
  265.         } else {
  266.         if (Src.Mode ==    ARPost)
  267.             if (Dest.Mode != ARPost)
  268.             Error (DestLoc,    ModeErr);
  269.             else
  270.             Error (SrcLoc, OperErr);
  271.         }
  272.     }
  273.     }
  274.  
  275.     if (Data911    IN AdrModeA) {        /* Data    in 9-11    (ADDQ/SUBQ) */
  276.     quick =    TRUE;
  277.     if (Src.Mode ==    Imm)
  278.         if ((Src.Value > 0)    && (Src.Value <= 8)) {
  279.         if (Src.Value <    8)    /* Data    of 8 is    coded as 000 */
  280.             Op |= Src.Value << 9;
  281.         } else
  282.         Error (SrcLoc, SizeErr);
  283.     else
  284.        Error (SrcLoc, OperErr);
  285.     }
  286.  
  287.     if (CntR911    IN AdrModeA) {    /* Only    Shift/Rotate use this */
  288.     if (Dest.Mode == DReg) {
  289.         Op = (Op & 0xF9FF) | Dest.Rn;
  290.         if (Size ==    Word) Op |= 0x0040;
  291.         if (Size ==    Long) Op |= 0x0080;
  292.         if (Src.Mode == DReg)
  293.         Op |= 0x0020 | (Src.Rn << 9);
  294.         else if (Src.Mode == Imm) {
  295.         quick =    TRUE;
  296.         /* Range Check */
  297.         if ((Src.Value > 0) && (Src.Value <= 8)) {
  298.             if (Src.Value < 8) /* Data of 8 is coded as    000 */
  299.             Op |= (Src.Value << 9);
  300.         } else
  301.             Error (SrcLoc, SizeErr);
  302.         } else
  303.         Error (SrcLoc, OperErr);
  304.     } else if (Dest.Mode ==    Null) {
  305.         Op = (Op & 0xFFE7) | 0x00C0;
  306.         EffAdr (&Src, (mea | aea));
  307.     } else
  308.         Error (SrcLoc, OperErr);
  309.     }
  310.  
  311.     if (Data03 IN AdrModeA) {        /* TRAP    Vector in 0-3 */
  312.     quick =    TRUE;
  313.     if (Src.Mode ==    Imm)
  314.         if ((Src.Value >= 0) && (Src.Value < 16))
  315.         Op |= Src.Value;
  316.         else
  317.         Error (SrcLoc, SizeErr);
  318.     else
  319.         Error (SrcLoc, OperErr);
  320.     }
  321.  
  322.     if (Data07 IN AdrModeA) {        /* Data    in 0-7 (MOVEQ) */
  323.     quick =    TRUE;
  324.     Op |= (Src.Value & 0x00FFL) | (Dest.Rn << 9);
  325.     if (Src.Mode !=    Imm)
  326.         Error (SrcLoc, ModeErr);
  327.     else if    (Dest.Mode != DReg)
  328.         Error (DestLoc, ModeErr);
  329.     else if    ((Src.Value < -128) || (Src.Value > 127))
  330.         Error (SrcLoc, SizeErr);
  331.     }
  332.  
  333.     if (OpM68D IN AdrModeA) {    /* DReg    in 6-8 (ADD/AND/OR/SUB)    */
  334.     if (Dest.Mode == DReg) {
  335.         Op |= (Dest.Rn << 9);
  336.         if ((Src.Mode == ARDir) && (Size ==    Byte))
  337.         Error (SrcLoc, SizeErr);
  338.     } else    /* Assume Src.Mode = DReg -- Error trapped elsewhere */
  339.         Op |= (Src.Rn << 9)    | 0x0100;
  340.  
  341.     if (Size == Word) Op |=    0x0040;
  342.     if (Size == Long) Op |=    0x0080;
  343.     }
  344.  
  345.     if (OpM68A IN AdrModeA) {    /* AReg    in 6-8 (ADDA/CMPA/SUBA)    */
  346.     if (Dest.Mode == ARDir)
  347.         Op |= (Dest.Rn << 9);
  348.     else
  349.         Error (DestLoc, ModeErr);
  350.  
  351.     if (Size == Byte) Error    (OpLoc+5, SizeErr);
  352.     if (Size == Word) Op |=    0x00C0;
  353.     if (Size == Long) Op |=    0x01C0;
  354.     }
  355.  
  356.     if (OpM68C IN AdrModeA) {        /* CMP (Compare) */
  357.     if (Dest.Mode == DReg)
  358.         Op |= (Dest.Rn << 9);
  359.     else
  360.         Error (DestLoc, ModeErr);
  361.  
  362.     if (Size == Byte) {
  363.         if (Src.Mode == ARDir)
  364.         Error (OpLoc+4,    SizeErr);
  365.     }
  366.     if (Size == Word) Op |=    0x0040;
  367.     if (Size == Long) Op |=    0x0080;
  368.     }
  369.  
  370.     if (OpM68X IN AdrModeA) {        /* EOR (Exclusive or) */
  371.     if (Src.Mode ==    DReg)
  372.         Op |= (Src.Rn << 9);
  373.     else
  374.         Error (SrcLoc, ModeErr);
  375.  
  376.     if (Size == Byte) Op |=    0x0100;
  377.     if (Size == Word) Op |=    0x0140;
  378.     if (Size == Long) Op |=    0x0180;
  379.     }
  380.  
  381.     if (OpM68S IN AdrModeA) {        /* EXT (Sign extension)    */
  382.     if (Src.Mode ==    DReg)
  383.         Op |= Src.Rn;
  384.     else
  385.         Error (SrcLoc, ModeErr);
  386.  
  387.     if (Size == Byte) Error    (OpLoc+4, SizeErr);
  388.     if (Size == Word) Op |=    0x0080;
  389.     if (Size == Long) Op |=    0x00C0;
  390.     }
  391.  
  392.     if (OpM68R IN AdrModeA) {        /* MOVEP (Register/memory) */
  393.     if ((Src.Mode == DReg) && (Dest.Mode ==    ARDisp)) {
  394.         if (Size ==    Byte) Error (OpLoc+6, SizeErr);
  395.         if (Size ==    Word) Op |= 0x0180;
  396.         if (Size ==    Long) Op |= 0x01C0;
  397.         Op |= (Src.Rn << 9)    | Dest.Rn;
  398.     } else if ((Src.Mode ==    ARDisp)    && (Dest.Mode == DReg))    {
  399.         if (Size ==    Byte) Error (OpLoc+6, SizeErr);
  400.         if (Size ==    Word) Op |= 0x0100;
  401.         if (Size ==    Long) Op |= 0x0140;
  402.         Op |= Src.Rn | (Dest.Rn << 9);
  403.     } else
  404.         Error (SrcLoc, ModeErr);
  405.     }
  406.  
  407.     if (OpM37 IN AdrModeA) {        /* EXG (Exchange registers) */
  408.     if ((Src.Mode == DReg) && (Dest.Mode ==    DReg))
  409.         Op |= 0x0040 | (Src.Rn << 9) | Dest.Rn;
  410.     else if    ((Src.Mode == ARDir) &&    (Dest.Mode == ARDir))
  411.         Op |= 0x0048 | (Src.Rn << 9) | Dest.Rn;
  412.     else if    ((Src.Mode == ARDir) &&    (Dest.Mode == DReg))
  413.         Op |= 0x0088 | (Dest.Rn << 9) | Src.Rn;
  414.     else if    ((Src.Mode == DReg) && (Dest.Mode == ARDir))
  415.         Op |= 0x0088 | (Src.Rn << 9) | Dest.Rn;
  416.     else
  417.         Error (SrcLoc, ModeErr);
  418.     }
  419.  
  420.     if (Bit811 IN AdrModeB) {    /* Bit operations using    bits 8-11 */
  421.     if (Src.Mode ==    DReg)
  422.         Op |= 0x0100 | (Src.Rn << 9);
  423.     else if    (Src.Mode == Imm)
  424.         Op |= 0x0800;
  425.     else
  426.         Error (SrcLoc, ModeErr);
  427.     }
  428.  
  429.     if (Size67 IN AdrModeB) {        /* Size    in bits    6-7 */
  430.      /*    if (Size == Byte) ; No action -- bits are already 0 */
  431.     if (Size == Word) Op |=    0x0040;
  432.     if (Size == Long) Op |=    0x0080;
  433.     }
  434.  
  435.     if (Size6 IN AdrModeB) {        /* Size    in bit 6 (MOVEM) */
  436.     if (Size == Byte) Error    (OpLoc+6, SizeErr);
  437.      /*    if (Size == Word) ; No Action -- bit is    already    0 */
  438.     if (Size == Long) Op |=    0x0040;
  439.     }
  440.  
  441.     if (Sz1213A    IN AdrModeB) {        /* Size    in 12-13 (MOVE)    */
  442.     if (Size == Byte) Op |=    0x1000;
  443.     if (Size == Word) Op |=    0x3000;
  444.     if (Size == Long) Op |=    0x2000;
  445.     }
  446.  
  447.     if (Sz1213 IN AdrModeB) {        /* Size    in 12-13 (MOVEA) */
  448.     Op |= (Dest.Rn << 9);
  449.     if (Size == Byte) Error    (OpLoc+6, SizeErr);
  450.     if (Size == Word) Op |=    0x3000;
  451.     if (Size == Long) Op |=    0x2000;
  452.     }
  453.  
  454.     if (EA05a IN AdrModeB)        /* Effective address - all */
  455.        if ((Dest.Mode == DReg) || (Dest.Mode ==    ARDir))
  456.        EffAdr (&Src, ea);
  457.        else
  458.        Error (DestLoc, ModeErr);
  459.  
  460.     if (EA05b IN AdrModeB)    /* Eff.    Addr. -    all except ARDir */
  461.     if (Dest.Mode == DReg) {
  462.        EffAdr (&Src, dea);
  463.        Op |= (Dest.Rn << 9);
  464.     } else
  465.         Error (DestLoc, ModeErr);
  466.  
  467.     if (EA05c IN AdrModeB)    /* BTST    */
  468.     EffAdr (&Dest, 0x0802);    /* All but ARDir/Imm */
  469.  
  470.     if (EA05d IN AdrModeB) {    /* All but PC relative & immediate */
  471.     EffAdr (&Dest, aea);
  472.     if ((Dest.Mode == ARDir) && (Size == Byte))
  473.         Error (OpLoc+5, SizeErr);
  474.     }
  475.  
  476.     if (EA05e IN AdrModeB) {    /* All but ARDir, PC relative, Imm */
  477.     if (Dest.Mode == Null)
  478.         EffAdr (&Src, (dea | aea));
  479.     else if    ((Src.Mode == Imm) || (Src.Mode    == DReg))
  480.         EffAdr (&Dest, (dea    | aea));
  481.     else
  482.         Error (SrcLoc, ModeErr);
  483.     }
  484.  
  485.     if (EA05f IN AdrModeB) {    /* JMP,    JSR, LEA, and PEA */
  486.     EffAdr (&Src, cea);
  487.     if (Rx911 IN AdrModeA)
  488.         if (Dest.Mode == ARDir)
  489.         Op |= (Dest.Rn << 9);        /* Address Reg. for    LEA */
  490.         else
  491.         Error (DestLoc,    ModeErr);   /* Must load Address Reg. */
  492.     else
  493.         if (Dest.Mode != Null)
  494.         Error (DestLoc,    OperErr);   /* No Dest.    unless LEA */
  495.     }
  496.  
  497.     if (EA05x IN AdrModeB) {        /* AND and OR */
  498.     if (Dest.Mode == DReg)
  499.         EffAdr (&Src, dea);
  500.     else if    (Src.Mode == DReg)
  501.         EffAdr (&Dest, mea | aea);
  502.     else
  503.         Error (SrcLoc, OperErr);
  504.     }
  505.  
  506.     if (EA05y IN AdrModeB) {        /* ADD and SUB */
  507.     if (Dest.Mode == DReg) {
  508.         EffAdr (&Src, ea);
  509.         if ((Src.Mode == ARDir) && (Size ==    Byte))
  510.            Error (OpLoc+4, SizeErr);
  511.     }
  512.     else if    (Src.Mode == DReg)
  513.         EffAdr (&Dest, (mea    | aea));
  514.     else
  515.         Error (SrcLoc, ModeErr);
  516.     }
  517.  
  518.     if (EA05z IN AdrModeB) {        /* MOVEM */
  519.     i = FALSE;                /* ExtL    flip indicator */
  520.     if (Src.Mode ==    MultiM)    {
  521.         EffAdr (&Dest, (mea    | aea |    0x0008));
  522.         if ((ExtL =    Src.Value) == 0)
  523.         ExtL = GetMultReg (SrcOp, (Dest.Mode ==    ARPre),    SrcLoc);
  524.         else
  525.         i = (Dest.Mode == ARPre);    /* Already have    mask */
  526.     } else if (Dest.Mode ==    MultiM)    {
  527.         Op |= 0x0400;            /* Set direction */
  528.         EffAdr (&Src, (mea | 0x0810));
  529.         if ((ExtL =    Dest.Value) == 0)
  530.         ExtL = GetMultReg (DestOp, (Src.Mode ==    ARPre),    DestLoc);
  531.         else
  532.         i = (Src.Mode == ARPre);
  533.     } else
  534.         Error (SrcLoc, OperErr);
  535.     if (i) {                /* Flip    ExtL */
  536.         j =    0;
  537.         for    (i = 0;    i < 8; i++)
  538.         j |= (ExtL & (1<<i)) <<    (15-i*2);
  539.         for    (i = 8;    i < 16;    i++)
  540.         j |= (ExtL & (1<<i)) >>    (i*2-15);
  541.         ExtL = j;
  542.     }
  543.     nO += 2;       /* extension is part of OpCode */
  544.     InstSize += 2;
  545.     }
  546.  
  547.     if (EA611 IN AdrModeB) {    /* Eff.    Addr. in 6-11 (MOVE) */
  548.     if (Dest.Mode == CCR) {            /* MOVE    to CCR */
  549.         Op = 0x44C0;
  550.         EffAdr (&Src, dea);
  551.     } else if (Dest.Mode ==    SR) {        /* MOVE    to SR */
  552.         Op = 0x46C0;
  553.         EffAdr (&Src, dea);
  554.     } else if (Src.Mode == SR) {        /* MOVE    from SR    */
  555.         Op = 0x40C0;
  556.         EffAdr (&Dest, dea | aea);
  557.     } else if (Dest.Mode ==    USP) {        /* MOVE    to USP */
  558.         Op = 0x4E60;
  559.         if (Src.Mode == ARDir)
  560.         Op |= Src.Rn;
  561.         else
  562.         Error (SrcLoc, ModeErr);
  563.     } else if (Src.Mode == USP) {        /* MOVE    from USP */
  564.         Op = 0x4E68;
  565.         if (Dest.Mode == ARDir)
  566.         Op |= Dest.Rn;
  567.         else
  568.         Error (DestLoc,    ModeErr);
  569.     } else {            /* General MOVE    instruction */
  570.         EffAdr (&Src, (ea |    xxx));
  571.         if ((Size == Byte) && (Src.Mode == ARDir))
  572.         Error (SrcLoc, SizeErr);
  573.         if (Src.Mode > 12)
  574.         Error (SrcLoc, ModeErr);
  575.         if (((1<<(Dest.Mode-1)) IN (dea|aea)) || (Dest.Mode>12))
  576.         Error (DestLoc,    ModeErr);
  577.         else if (Dest.Mode < 8) /* Register    direct or indirect */
  578.         Op |= ((Dest.Mode - 1) << 6) | (Dest.Rn    << 9);
  579.         else        /* Absolute, PC relative, or immediate */
  580.         Op |= 0x01C0 | ((Dest.Mode - 8)    << 9);
  581.         OperExt (&Dest);        /* Set up extension word */
  582.     }
  583.     }
  584.  
  585.     if ((Dest.Mode == CCR) && (Src.Mode    == Imm)) {
  586.     if ((Size67 IN AdrModeB)
  587.     && (EA05e IN AdrModeB)
  588.     && (Exten IN AdrModeB))
  589.         if (0x0400 IN Op)     /* not    ANDI/EORI/ORI */
  590.         Error (DestLoc,    ModeErr);
  591.         else
  592.         Op = (Op & 0xFF00) | 0x003C;
  593.     }
  594.  
  595.     if ((Dest.Mode == SR) && (Src.Mode == Imm))    {
  596.     if ((Size67 IN AdrModeB)
  597.     && (EA05e IN AdrModeB)
  598.     && (Exten IN AdrModeB))
  599.         if (0x0400 IN Op)     /* not    ANDI/EORI/ORI */
  600.         Error (DestLoc,    ModeErr);
  601.         else
  602.         Op = (Op & 0xFF00) | 0x007C;
  603.     }
  604.  
  605.     ObjOp = Op;
  606.     InstSize +=    2;
  607.     nO += 2;
  608.     if (nO > 2)    {
  609.     templong = ExtL;            /* Add extension word */
  610.     ObjOp =    (ObjOp << 16) |    (templong & 0x0000FFFFL);
  611.     }
  612.     if ((AdrModeA != 0)    || (AdrModeB !=    0)) {
  613.     InstSize += (nS    = GetInstModeSize (Src.Mode));
  614.     ObjSrc = Src.Value;
  615.     InstSize += (nD    = GetInstModeSize (Dest.Mode));
  616.     ObjDest    = Dest.Value;
  617.     }
  618.     if (quick) {
  619.     InstSize -= nS;        /* Source operand is in    Op */
  620.     nS = 0;
  621.     }
  622.  
  623.     if ((nS != 0) && (Src.Hunk != ABSHUNK)) {    /* SrcOp relocatable */
  624.     if ((Src.Mode == AbsL)
  625.     || (Src.Mode ==    AbsW)
  626.     || (Src.Mode ==    ARDisp)
  627.     || (Src.Mode ==    PCDisp)
  628.     || (Src.Mode ==    Imm)) {
  629.         templong = AddrCnt + nO;        /* 16-bit relocatable */
  630.         PutRel (Srec, templong, Src.Hunk, nS);
  631.     }
  632.     if ((Src.Mode==ARDisX) || (Src.Mode==PCDisX)) {
  633.         templong = AddrCnt + nO + 1;    /* 8-bit relocatable */
  634.         PutRel (Srec, templong, Src.Hunk, 1);
  635.     }
  636.     }
  637.     if ((nD != 0) && (Dest.Hunk    != ABSHUNK)) {    /* DestOp relocatable */
  638.     if ((Dest.Mode == AbsL)
  639.     || (Dest.Mode == AbsW)
  640.     || (Dest.Mode == ARDisp)
  641.     || (Dest.Mode == PCDisp)
  642.     || (Dest.Mode == Imm)) {
  643.         templong = AddrCnt + nO + nS;    /* 16-bit relocatable */
  644.         PutRel (Srec, templong, Dest.Hunk, nD);
  645.     }
  646.     if ((Dest.Mode==ARDisX)    || (Dest.Mode==PCDisX))    {
  647.         templong = AddrCnt + nO + nS + 1;    /* 8-bit relocatable */
  648.         PutRel (Srec, templong, Dest.Hunk, 1);
  649.     }
  650.     }
  651.  
  652.     AddrAdv = InstSize;
  653. }
  654.